package com.zc.angelica.config.sucurity.filter;
import cn.hutool.json.JSONUtil;
import cn.hutool.jwt.JWTUtil;
import com.alibaba.fastjson.JSONObject;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.zc.angelica.config.sucurity.handler.LoginToken;
import com.zc.angelica.config.sucurity.handler.MyAuthenticationProvider;
import com.zc.angelica.entity.Account;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.stereotype.Component;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.*;
import java.util.concurrent.atomic.AtomicBoolean;

/**
 * 登录校验
 *
 * 第一种方式 我们这里用框架自带的 过滤器实现
 * 第二种方式 可以自己实现登录接口  去认证 其实也是 AuthenticationManager。authenticate 去认证
 *
 * @author Json
 * @date 2021/11/1 13:47
 */
public class JwtLoginFilter extends UsernamePasswordAuthenticationFilter {

    private MyAuthenticationProvider myAuthenticationProvider;

    public JwtLoginFilter(MyAuthenticationProvider myAuthenticationProvider) {
        this.myAuthenticationProvider = myAuthenticationProvider;
    }

    @Override
    public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException {
        // 相当于登录 认证
        String username = obtainUsername(request);
        String password = obtainPassword(request);
        LoginToken loginToken = new LoginToken(username,password);
        loginToken.setDetails(request);
        return myAuthenticationProvider.authenticate(loginToken);
    }

    /**
     * 一旦调用 springSecurity认证登录成功，立即执行该方法
     */
    @Override
    protected void successfulAuthentication(HttpServletRequest request, HttpServletResponse response, FilterChain chain, Authentication authResult) throws IOException, ServletException {
        Account account = (Account) authResult.getPrincipal();
        Calendar calendar = new GregorianCalendar();
        Date date = new Date();
        calendar.setTime(date);
        calendar.add(Calendar.MINUTE, 30);
        AtomicBoolean lasting = new AtomicBoolean(false);
        if (account.getLasting()!=null&&account.getLasting().size()>0){
            String clientCode = request.getHeader("clientCode");
            if (clientCode!=null&&!clientCode.equals("")){
                account.getLasting().forEach(item -> {
                    if (item.getClientCode().equals(clientCode)){
                        if (item.getPersistentLogin()==2){
                            lasting.set(true);
                        }
                    }
                });
            }
        }
        Map<String, Object> jwtMap = new HashMap<String, Object>() {
            private static final long serialVersionUID = 1L;
            {
                put("sub", account.getId());
                put("name", account.getUsername());
                put("lasting", lasting);
                put("exp", calendar.getTime());
            }
        };
        String token = JWTUtil.createToken(jwtMap, "zhiruo".getBytes());
        response.setHeader("Authorization",token);
        Map<String, Object> paramMap = new HashMap<>();
        paramMap.put("code", "200");
        paramMap.put("token", token);
        paramMap.put("message", "登录成功！");

        //设置返回请求头
        response.setContentType("application/json;charset=utf-8");
        //写出流
        PrintWriter out = response.getWriter();
        out.write(JSONObject.toJSONString(paramMap));
        out.flush();
        out.close();
    }

    /**
     * 一旦调用 springSecurity认证失败 ，立即执行该方法
     */
    @Override
    protected void unsuccessfulAuthentication(HttpServletRequest request, HttpServletResponse response, AuthenticationException ex) throws IOException {
        Map<String, Object> paramMap = new HashMap<>();
        paramMap.put("code", "401");
        paramMap.put("message", ex.getMessage());
        //设置返回请求头
        response.setContentType("application/json;charset=utf-8");
        //写出流
        PrintWriter out = response.getWriter();
        out.write(JSONObject.toJSONString(paramMap));
        out.flush();
        out.close();
    }
}